#include "HttpConnection.h"

#include "LogicSystem.h"

HttpConnection::HttpConnection(boost::asio::io_context& ioc) : _socket(ioc) {}

tcp::socket& HttpConnection::GetSocket() { return _socket; }

void HttpConnection::Start() {
  auto self = shared_from_this();

  // 处理异步读事件
  http::async_read(
      _socket, _buffer, _request,
      [self](beast::error_code ec, std::size_t bytes_transferred) {
        try {
          if (ec) {
            std::cout << "http read err is " << ec.what() << std::endl;
            return;
          }

          // std::string raw_data =
          //    boost::beast::buffers_to_string(self->_buffer.data());

          //// 打印原始数据
          // std::cout << "Raw buffer data: " << raw_data
          //          << std::endl;

          // 打印请求路径
          std::cout << "Request Path: " << self->_request.target() << std::endl;

      // 写日志
#ifdef LOG_DEBUG
          g_logs->info(
              "IP:[{0}] Port:[{1}] HTTP Method:[{2}] Request Path:[{3}]",
              self->_socket.remote_endpoint().address().to_string(),
              self->_socket.remote_endpoint().port(),
              self->_request.method_string(), self->_request.target());
#endif

          // 处理得到数据
          // boost::ignore_unused(bytes_transferred);
          self->HandleReq();
          self->CheckDeadline();

        } catch (std::exception& e) {
          std::cout << "ERROR: " << e.what() << std::endl;
        }
      });
}

void HttpConnection::CheckDeadline() {
  auto self = shared_from_this();
  _deadline.async_wait([self](beast::error_code ec) {
    if (!ec) {
      // 定时器出发时就会断开Socket
      self->_socket.close(ec);
    }
  });
}

void HttpConnection::PreParseGetParam() {
  // 提取url
  auto url = _request.target();

  // 查找字符串开始的位置，(url中?开始的位置）
  auto query_pos = url.find('?');

  // std::string::npos是一个特殊常量值。代表没有匹配带子字符串
  // 当没有找到'?'时，代表此次get请求没有带参数
  if (query_pos == std::string::npos) {
    _get_url = url;
    return;
  }

  // get请求带参数的时候

  _get_url = url.substr(0, query_pos);
  std::string query_string = url.substr(query_pos + 1);
  std::string key;
  std::string value;
  size_t pos = 0;
  while ((pos = query_string.find('&')) != std::string::npos) {
    auto pair = query_string.substr(0, pos);
    size_t eq_pos = pair.find('=');
    if (eq_pos != std::string::npos) {
      key = UrlDecode(pair.substr(0, eq_pos));
      value = UrlDecode(pair.substr(eq_pos + 1));
      _get_params[key] = value;
    }
    query_string.erase(0, pos + 1);
  }

  // 处理最后一个参数对（没用&分隔开）
  if (!query_string.empty()) {
    size_t eq_pos = query_string.find('=');
    if (eq_pos != std::string::npos) {
      key = UrlDecode(query_string.substr(0, eq_pos));
      value = UrlDecode(query_string.substr(eq_pos + 1));
      _get_params[key] = value;
    }
  }
}

unsigned char HttpConnection::FromHex(unsigned char x) {
  unsigned char y;
  if (x >= 'A' && x <= 'Z')
    y = x - 'A' + 10;
  else if (x >= 'a' && x <= 'z')
    y = x - 'a' + 10;
  else if (x >= '0' && x <= '9')
    y = x - '0';
  else
    assert(0);
  return y;
}

std::string HttpConnection::UrlDecode(const std::string& str) {
  std::string strTemp = "";
  size_t length = str.length();
  for (size_t i = 0; i < length; i++) {
    //还原+为空
    if (str[i] == '+') strTemp += ' ';
    //遇到%将后面的两个字符从16进制转为char再拼接
    else if (str[i] == '%') {
      assert(i + 2 < length);
      unsigned char high = FromHex((unsigned char)str[++i]);
      unsigned char low = FromHex((unsigned char)str[++i]);
      strTemp += high * 16 + low;
    } else
      strTemp += str[i];
  }
  return strTemp;
}

void HttpConnection::WriteResponse() {
  auto self = shared_from_this();

  // 设置回应消息正文长度
  _response.content_length(_response.body().size());

  http::async_write(_socket, _response,
                    [self](beast::error_code ec, std::size_t) {
                      // 因为是短链接，发送完就关闭链接
                      self->_socket.shutdown(tcp::socket::shutdown_send, ec);

                      // 取消定时器
                      self->_deadline.cancel();
                    });
}

void HttpConnection::HandleReq() {
  // 设置http版本
  _response.version(_request.version());
  // 设置为短连接
  _response.keep_alive(false);

  if (_request.method() == http::verb::get) {
    // Http协议第一部分 GET /index.html HTTP/1.1
    // _request.target() 取出的就是：/index.html

    PreParseGetParam();

    bool success =
        LogicSystem::GetInstance()->HandleGet(_get_url, shared_from_this());
    if (false == success) {
      _response.result(http::status::not_found);
      _response.set(http::field::content_type, "text/plain");
      beast::ostream(_response.body()) << "url not found\r\n";
      WriteResponse();
      return;
    }

    _response.result(http::status::ok);
    _response.set(http::field::server, "GateServer");
    WriteResponse();
    return;
  }

  if (_request.method() == http::verb::post) {
    bool success = LogicSystem::GetInstance()->HandlePost(_request.target(),
                                                          shared_from_this());
    if (!success) {
      _response.result(http::status::not_found);
      _response.set(http::field::content_type, "text/plain");
      beast::ostream(_response.body()) << "url not found\r\n";
      WriteResponse();
      return;
    }

    _response.result(http::status::ok);
    _response.set(http::field::server, "GateServer");
    WriteResponse();
    return;
  }
}
